package controller

import (
	"GoTime/models"
	"GoTime/response"
	. "GoTime/utils"
	"encoding/json"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"xorm.io/builder"
	"xorm.io/xorm"
)

func GetStudentList(c *gin.Context) {
	var (
		studentList []response.StudentListResponse
		err         error
		page        int
		pageSize    int
		offset      int
		count       int64
	)
	page = cast.ToInt(c.DefaultQuery("page", "0"))
	pageSize = cast.ToInt(c.DefaultQuery("pageSize", "10"))
	offset = (page - 1) * pageSize
	filter := builder.NewCond()
	if username := c.Query("name"); username != "" {
		filter = filter.And(builder.Like{"u.name", username})
	}
	if idNumber := c.Query("id_number"); idNumber != "" {
		filter = filter.And(builder.Like{"u.id_number", idNumber})
	}
	if phone := c.Query("phone"); phone != "" {
		filter = filter.And(builder.Like{"u.phone", phone})
	}
	if idType := c.Query("id_type"); idType != "" {
		filter = filter.And(builder.Eq{"u.id_type": idType})
	}
	if operationStatus := c.Query("operation_status"); operationStatus != "" {
		filter = filter.And(builder.Eq{"st.operation_status": operationStatus})
	}
	if trainingCarType := c.Query("training_car_type"); trainingCarType != "" {
		filter = filter.And(builder.Eq{"st.training_car_type": trainingCarType})
	}
	if chargeMode := c.Query("charge_mode"); chargeMode != "" {
		filter = filter.And(builder.Eq{"sd.charge_mode": chargeMode})
	}
	if startTime := c.Query("start_time"); startTime != "" {
		filter = filter.And(builder.Gte{"st.sign_in_time": startTime})
	}
	if loginStatus := c.Query("login_status"); loginStatus != "" {
		filter = filter.And(builder.Eq{"st.login_status": loginStatus})
	}
	if status := c.Query("status"); status != "" {
		filter = filter.And(builder.Eq{"st.status": status})
	}
	if recordStatus := c.Query("record_status"); recordStatus != "" {
		filter = filter.And(builder.Eq{"st.record_status": recordStatus})
	}
	if endTime := c.Query("end_time"); endTime != "" {
		filter = filter.And(builder.Lte{"st.sign_in_time": endTime})
	}
	if className := c.Query("class_name"); className != "" {
		filter = filter.And(builder.Eq{"sd.class_name": className})
	}
	count, studentList, err = new(models.Student).GetStudentList(c.Query("school_id"), filter, offset, pageSize)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "获取学生列表失败", "data": err})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "获取学生列表成功", "data": gin.H{"count": count, "list": studentList}})
	return
}

func AddStudent(c *gin.Context) {
	var (
		charstand *models.CharStandard // 定义一个指向CharStandard模型的指针，用于存储班型信息
		student   *models.Student      // 定义一个Student模型，用于存储学员信息
		user      *models.User         // 定义一个User模型，用于存储用户信息
		portrait  *models.Portrait     // 定义一个Portrait模型，用于存储用户头像信息
		err       error                // 定义一个error变量，用于存储错误信息
	)

	// 绑定参数
	// 尝试从请求中绑定数据到student模型
	if err = c.ShouldBind(&student); err != nil {
		// 如果绑定失败，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误", "data": err.Error()})
		return
	}

	// 尝试从请求的JSON体中绑定数据到user模型
	if err = c.ShouldBind(&user); err != nil {
		// 如果绑定失败，返回错误信息
		log.Println(err)
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误", "data": err.Error()})
		return
	}

	// 尝试从请求的JSON体中绑定数据到portrait模型
	if err = c.ShouldBind(&portrait); err != nil {
		// 如果绑定失败，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误", "data": err.Error()})
		return
	}

	// 验证信息
	// 根据手机号检查系统中是否已存在该用户的报名信息
	if phoneE, _ := user.GetUserByPhone(user.Phone); phoneE {
		// 如果存在，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "该手机号报名信息已存在系统"})
		return
	} else if idNumE, _ := user.CheckExitUserByNum(user.IdNumber, "4"); idNumE {
		// 根据身份证号检查系统中是否已存在该用户的报名信息，类型为4
		// 如果存在，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "该证件号报名信息已存在系统"})
		return
	}

	// 根据学校ID获取驾校信息
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(c.PostForm("school_id")))
	if err != nil || !ok {
		// 如果获取学校信息失败或驾校不存在，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	}

	// 如果驾校所在城市为371700，该驾校不支持在线报名
	if school.City == "371700" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "该驾校不支持在线报名"})
		return
	}

	// 检查驾校状态，如果状态为2或3，驾校不能录入学员，请联系客服人员
	if school.Status == 2 || school.Status == 3 {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "该驾校不能录入学员，请联系客服人员"})
		return
	} else if school.Status == 4 {
		// 检查驾校状态，如果状态为4，驾校不能录入学员，请联系当地管理人员
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "该驾校不能录入学员，请联系当地管理人员"})
		return
	}

	// 检查驾校剩余可注册学员数是否足够
	if school.Usednum < 2 {
		// 如果剩余名额足够，继续执行
	} else {
		temp := school.Registernum
		count := temp - school.Usednum
		if count <= 0 {
			// 如果剩余名额不足，返回错误信息
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "剩余可注册学员数不够,请联系服务商购买"})
			return
		}
	}

	// 设置用户类型为4，表示学员
	user.Type = "4"
	// 移除姓名中的空格
	user.Name = strings.Replace(user.Name, " ", "", -1)
	// 去除手机号和身份证号中的多余空格
	user.Phone = strings.TrimSpace(user.Phone)
	user.IdNumber = strings.TrimSpace(user.IdNumber)

	// 生成用户密码，如果身份证号长度小于等于12，则默认密码为123456的MD5值
	// 否则，密码为身份证号后6位的MD5值
	if len([]rune(user.IdNumber)) <= 12 {
		user.Password = Md5("123456")
	} else {
		user.Password = Md5(user.IdNumber[12:18])
	}

	// 根据操作状态设置学员信息
	if student.OperationStatus == "1" {
		// 如果操作状态为1，表示已有驾驶证
		if student.LicenceNumber == "" {
			// 如果驾驶证号为空，返回错误信息
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "请输入驾驶证号"})
			return
		}
		student.LicenceGrantDate, _ = time.Parse("2006-01-02", c.PostForm("licence_grace_date"))
		// 设置驾驶证类型
		student.DrivingCarType = c.PostForm("driving_car_type")
	} else {
		// 如果操作状态不是1，表示尚未有驾驶证
		student.DrivingCarType = ""
	}

	// 设置学员关联的用户ID和驾校ID
	student.UserId = user.Id
	student.SchoolId = school.Id

	// 设置学员的报名时间和添加时间
	student.SignInTime, _ = time.Parse("2006-01-02", c.PostForm("sign_in_date"))
	student.Addtime = time.Now()

	// 初始化学员各科目考试状态
	student.Subject1isreport = "0"
	student.Subject2isreport = "0"

	// 如果驾校所在省份为140000（假设为山西），则默认设置科目三为已上报状态
	if school.Province == "140000" {
		student.Subject3isreport = "1"
	} else {
		student.Subject3isreport = "0"
	}

	// 初始化科目四考试状态
	student.Subject4isreport = "0"

	// 根据班型ID获取班型信息
	charId, _ := strconv.Atoi(c.PostForm("charstandard_id"))
	if charstand, err = new(models.CharStandard).GetSignChatStandard(charId); charstand.Id == 0 {
		// 如果班型信息获取失败或班型ID为0，返回班型错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "班型错误"})
		return
	}

	// 定义一个指向TrainCarinfo模型的指针，用于存储培训车型信息
	var trainCarinfo *models.TrainCarinfo
	trainCarinfo = new(models.TrainCarinfo)

	// 根据培训车型名称获取培训车型信息
	if trainCarinfo, err = new(models.TrainCarinfo).GetTrainCarinfo(c.PostForm("training_car_type")); trainCarinfo.Id == 0 {
		// 如果培训车型信息获取失败或培训车型ID为0，返回培训车型错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "培训车型错误"})
		return
	}

	// 设置学员报名状态、总费用、已支付费用、支付状态、教练ID、班型ID
	student.RecordStatus = "0"
	student.TotalMoney = charstand.Price
	student.PayMoney = 0
	student.PayStatus = 0
	student.CoachId = 0
	student.CharstandardId = charstand.Id

	// 根据驾校省份设置学员的SID（假设为操作员ID）
	if school.Province == "420000" || school.Province == "610000" { // 假设420000为湖北，610000为陕西
		student.Sid = c.PostForm("operator")
		if school.UserId != cast.ToInt(c.PostForm("user_id")) {
			user.Sid = cast.ToInt(c.PostForm("user_id"))
		}
	}

	// 设置学员的使用状态为1（表示使用中）
	student.Isused = "1"

	// 初始化学员的科目剩余学时
	student.Remainhours1 = trainCarinfo.HoursSubject1 * 45
	student.Remainhours2 = trainCarinfo.HoursSubject2 * 45
	student.Remainhours3 = trainCarinfo.HoursSubject3 * 45
	student.Remainhours4 = trainCarinfo.HoursSubject4 * 45

	// 根据是否保留报名信息设置学员的审批状态
	if c.PostForm("retain") == "1" {
		student.ApprovalStatus = "0"
		student.RecordStatus = "0"
	} else {
		//NOTE: 向全国监管平台注册学员信息后, 获取全国学员编号
		//if student, err = student.GetInstitution(school.InstitutionCode, user, portrait.InstitutionCode, "", school.Province, school.City); err != nil {
		//	//Resp(c, 201, err.Error(), nil)
		//	return
		//}
		student.ApprovalStatus = "1"
		student.RecordStatus = "1"
	}
	var engine *xorm.Engine
	engine = models.Engine
	session := engine.NewSession()
	defer session.Close()
	// add Begin() before any action
	err = session.Begin()
	user.Isused = "1"
	if _, err = session.Insert(user); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	portrait.UserId = user.Id
	portrait.AddTime = time.Now()
	portrait.TerminalId = 0
	portrait.Drilicimg = c.PostForm("drilicimg")
	portrait.CardUrl = c.PostForm("card_url")
	_, err = session.Insert(portrait)
	if err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	student.UserId = user.Id
	student.PortraitId = portrait.Id
	student.FingerId = 0
	student.SignInTime, _ = time.Parse("2006-01-02", c.PostForm("sign_in_date"))
	if c.PostForm("licence_grace_date") != "" {
		student.LicenceGrantDate, _ = time.Parse("2006-01-02", c.PostForm("licence_grace_date"))
	}
	if _, err := session.Insert(student); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	school.Usednum = school.Usednum + 1
	if _, err = session.Exec("update dts_school set usednum=? where id=?", school.Usednum, school.Id); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	//请求百度人脸识别接口
	log.Println("百度人脸识别接口：", user.Phone, user.IdNumber)
	if err = BaiduCheck(portrait.ImageUrl, user.Phone, user.IdNumber, school.Province); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	err = session.Commit()
	if err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	// 最后加上推送快鸭 kyPush 接口
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "学员添加成功", "data": nil})
	return
}

func EditStudent(c *gin.Context) {
	var (
		student   *models.Student
		portrait  *models.Portrait
		user      *models.User
		school    models.School
		charstand *models.CharStandard
		err       error
		ok        bool
	)

	if c.PostForm("student_id") == "" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员参数不能为空"})
		return
	}
	// 根据学校ID获取驾校信息
	if ok, school, err = new(models.School).GetSchoolById(cast.ToInt(c.PostForm("school_id"))); err != nil || !ok {
		// 如果获取学校信息失败或驾校不存在，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	}
	if school.City == "371700" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "该驾校不支持在线报名"})
		return
	}
	user = new(models.User)
	portrait = new(models.Portrait)
	student = new(models.Student)
	//根据id查询学员信息
	if ok, student, err = new(models.Student).GetStudentById(c.PostForm("student_id")); err != nil || !ok {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员不存在"})
		return
	}
	//return
	if c.Request.Method == "POST" {
		if err = c.ShouldBind(user); err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return
		}
		user.Name = strings.Replace(user.Name, " ", "", -1)
		if err = c.ShouldBind(student); err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return
		}
		if err = c.ShouldBind(portrait); err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return
		}
		if student.OperationStatus == "1" {
			log.Println(student.OperationStatus)
			log.Println(c.PostForm("licence_number"))
			if student.LicenceNumber = c.PostForm("licence_number"); student.LicenceNumber == "" {
				c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "增领驾驶证号不能为空"})
				return
			}
			student.LicenceGrantDate, _ = time.Parse("2006-01-02", c.PostForm("licence_grace_date"))
		}
		log.Println(student.LicenceNumber)
		student.Subject1isreport = "0"
		student.Subject2isreport = "0"
		student.Subject3isreport = "0"
		student.Subject4isreport = "0"
		student.IsImport = 0
		// charstandid, _ := strconv.Atoi(c.PostForm("charstandard_id"))
		// if charstand, err = new(models.CharStandard).GetSignChatstandart(charstandid); charstand.Id == 0 {
		// 	Resp(c, 201, "参数错误", nil)
		// 	return
		// }
		// if c.PostForm("training_car_type") != charstand.TrainingCarType {
		// 	Resp(c, 201, "培训车型与选择的缴费类型的培训车型不符", nil)
		// 	return
		// }
		// student.CharstandardId = charstandid
		student.RecordStatus = "0"
		student.OperationStatus = c.PostForm("operation_status")
		if student.OperationStatus == "1" || student.OperationStatus == "11" || student.OperationStatus == "12" {
			student.LicenceNumber = c.PostForm("licence_number")
			student.LicenceGrantDate, _ = time.Parse("2006-01-02", c.PostForm("licence_grace_date"))
		} else {
			student.LicenceNumber = ""
		}

		if c.PostForm("charstandard_id") != "" {
			student.CharstandardId, _ = strconv.Atoi(c.PostForm("charstandard_id"))
		}
		var engine *xorm.Engine
		engine = models.Engine
		session := engine.NewSession()
		defer session.Close()
		//var portraitface m.Portrait
		if c.PostForm("portrait_code") != "" {
			//-----------------------------添加头像图片
			if student.PortraitId > 0 {
				//更新
				_, *portrait, _ = new(models.Portrait).GetStudentPortraitById(int64(student.PortraitId))
				portrait.ImageUrl = c.PostForm("image_url")
				portrait.InstitutionCode = c.PostForm("portrait_code")
				portrait.UserId = student.UserId
				portrait.Drilicimg = c.PostForm("drilicimg")
				portrait.CardUrl = c.PostForm("card_url")
				if portrait, err = portrait.Edit("image_url", "institution_code", "user_id,drilicimg", "card_url"); err != nil {
					session.Rollback()
					c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
					return
				}
			} else {
				portrait.UserId = student.UserId
				portrait.AddTime = time.Now()
				portrait.TerminalId = 0
				portrait.Drilicimg = c.PostForm("drilicimg")
				portrait.CardUrl = c.PostForm("card_url")
				_, err = session.Insert(portrait)
				if err != nil {
					session.Rollback()
					c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
					return
				}
				student.PortraitId = portrait.Id
			}
		} else if student.PortraitId != 0 {
			portrait.UserId = student.UserId
			if portrait, err = portrait.Edit("user_id"); err != nil {
				session.Rollback()
				c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
				return
			}
		}

		//判断是学员编码如果为空
		if student.InstitutionCode == "" {
			//if school.Province != "420000" {
			//	if charstand, err = new(models.CharStandard).GetSignChatstandart(student.CharstandardId); charstand.Id == 0 {
			//		session.Rollback()
			//		Resp(c, 201, "班型错误", nil)
			//		return
			//	}
			//}
			if charstand, err = new(models.CharStandard).GetSignChatStandard(student.CharstandardId); charstand.Id == 0 {
				session.Rollback()
				c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "班型错误"})
				return
			}

			//判断student.Portrait_code
			if c.PostForm("portrait_code") != "" {
				if student, err = student.GetInstitution(school.InstitutionCode, user, portrait.InstitutionCode, "", school.Province, school.City); err != nil {
					session.Rollback()
					c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
					return
				}
				if !student.Edit("institution_code", "portrait_id", "pdf_url", "operation_status", "driving_car_type", "training_car_type", "status", "record_status", "licence_number", "sign_in_time", "licence_grant_date", "charstandard_id", "is_import") {
					session.Rollback()
					c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "编辑失败"})
					return
				}

			} else {
				session.Rollback()
				c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "头像不能为空"})
				return
			}
		} else {
			if !student.Edit("portrait_id", "istransfer", "operation_status", "pdf_url", "driving_car_type", "training_car_type", "status", "record_status", "licence_number", "sign_in_time", "licence_grant_date", "charstandard_id", "is_import") {
				session.Rollback()
				c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "头像不能为空"})
				return
			}
		}
		user.Id = student.UserId
		user.Phone = user.Phone
		if !user.Edit("name", "sex", "nation", "phone", "mail", "address", "nationality", "isotherprovince", "birthday", "icaddress") {
			session.Rollback()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "编辑失败"})
			return
		}
		if err = student.RecordStudent(school.InstitutionCode, user, school.Province, portrait.InstitutionCode, "", portrait.ImageUrl, school.City, portrait.Drilicimg); err != nil {
			if strings.Contains(err.Error(), "已被其它驾校") {
				c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "备案失败，该学员(编号" + student.InstitutionCode + ")已被其它驾校备案！"})
				return
			}
			if strings.Contains(err.Error(), "已被其他计时平台") {
				c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "备案失败，该学员(编号" + student.InstitutionCode + ")已被其他计时平台或驾培机构经备案！"})
				return
			}
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return

		}
		// 武汉学院备案到易学车
		//if c.PostForm("province") == "420000" {
		//	// req_type = 3
		//	reqData := map[string]interface{}{
		//		"inscode":     school.InstitutionCode,
		//		"stunum":      student.InstitutionCode,
		//		"cardtype":    user.IdType,
		//		"idcard":      user.IdNumber,
		//		"nationality": user.Nationality,
		//		"name":        user.Name,
		//		"sex":         user.Sex,
		//		"phone":       user.Phone,
		//		"photoPath":   portrait.ImageUrl,
		//		"busitype":    student.OperationStatus,
		//		"traintype":   student.TrainingCarType,
		//		"applydate":   student.SignInTime.Format("20060102"),
		//		"isTime":      1,
		//	}
		//	if err := WuhanSignReq("student", reqData, 3, c.PostForm("province"), c.PostForm("city"), "POST"); err != nil {
		//		//return c, err
		//	}
		//}
		student.RecordStatus = "1"
		_, err = session.Exec("update dts_student set record_status=?  where id = ?", "1", student.Id)
		if err != nil {
			session.Rollback()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return
		}
		// 百度人脸识别
		log.Println("百度人脸识别接口：", user.Phone, user.IdNumber)
		if err = BaiduCheck(portrait.ImageUrl, user.Phone, user.IdNumber, school.Province); err != nil {
			session.Rollback()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return
		}
		err = session.Commit()
		if err != nil {
			session.Rollback()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return
		}
		// 最后加上推送快鸭 kyPush 接口
		c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "编辑成功"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "编辑失败"})
	return
}

func StudentInfoQuery(c *gin.Context) {
	// 声明多个变量：url用于存储请求的URL，retMap用于存储API请求的返回结果，reqType用于存储请求类型，err用于存储错误信息
	var (
		url     string
		retMap  map[string]interface{}
		reqType int64
		err     error
	)

	// 从GET请求查询参数中获取"student_id"参数
	studentId := c.Query("student_id")

	// 如果"student_id"参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
	if studentId == "" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 根据获取到的studentId查询学员信息，并检查是否有错误或学员是否存在
	ok, student, err := new(models.Student).GetStudentById(studentId)
	if err != nil || !ok {
		// 如果查询学员信息时发生错误或学员不存在，返回JSON格式的错误信息，错误码为201，消息为“学员不存在”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员不存在"})
		return // 结束函数执行
	}

	// 根据学员的UserId查询用户信息，并检查是否有错误
	user, err := new(models.User).GetUserById(student.UserId)
	if err != nil {
		// 如果查询用户信息时发生错误，返回JSON格式的错误信息，错误码为201，消息为“查询学员信息失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "查询学员信息失败"})
		return // 结束函数执行
	}

	// 查询指定驾校ID的驾校信息，并检查是否有错误或驾校是否存在
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(student.SchoolId))
	if err != nil || !ok {
		// 如果查询驾校信息时发生错误或驾校不存在，返回JSON格式的错误信息，错误码为201，消息为“查询驾校信息失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "查询驾校信息失败"})
		return // 结束函数执行
	}

	// 进行备案，通过GetSignURL函数获取备案请求的URL，并检查是否有错误
	if url, err = GetSignURL(user.Name+"-stuinfoquery-"+user.IdNumber+"-"+student.TrainingCarType, nil, reqType, school.Province, school.City); err != nil {
		// 如果获取URL时发生错误，返回JSON格式的错误信息，错误码为201，消息为具体的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return // 结束函数执行
	}

	// 声明一个ApiLog对象用于记录API请求日志
	var apiLog models.ApiLog

	// 设置ApiLog对象的URL、Param、Method和Time字段
	apiLog.Url = url
	apiLog.Param = ""
	apiLog.Method = "POST"
	apiLog.Time = time.Now()

	// 发送API请求，并检查是否有错误
	if retMap, err = APIReq(url, nil, "GET"); err != nil {
		// 将API请求的返回结果转换为JSON字符串，并赋值给api_log的Result字段
		result, _ := json.Marshal(retMap)
		apiLog.Result = string(result)
		apiLog.Add() // 将API请求日志添加到数据库
		// 如果发送API请求时发生错误，返回JSON格式的错误信息，错误码为201，消息为具体的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return // 结束函数执行
	}

	// 将API请求的返回结果转换为JSON字符串，并赋值给api_log的Result字段
	result, _ := json.Marshal(retMap)
	apiLog.Result = string(result)
	apiLog.Add() // 将API请求日志添加到数据库

	// 如果API请求成功，返回JSON格式的成功信息，错误码为201，消息为“成功”，包含返回的数据
	c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "成功", "data": retMap})
	return // 结束函数执行

}

func StudentTransferApply(c *gin.Context) {
	// 声明多个变量：url用于存储请求的URL，retMap用于存储API请求的返回结果，reqType用于存储请求类型，err用于存储错误信息
	var (
		url     string
		retMap  map[string]interface{}
		reqType int64
		err     error
	)

	// 从GET请求查询参数中获取"student_id"参数
	studentId := c.Query("student_id")

	// 如果"student_id"参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
	if studentId == "" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 根据获取到的studentId查询学员信息，并检查是否有错误或学员是否存在
	ok, student, err := new(models.Student).GetStudentById(studentId)
	if err != nil || !ok {
		// 如果查询学员信息时发生错误或学员不存在，返回JSON格式的错误信息，错误码为201，消息为“学员不存在”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员不存在"})
		return // 结束函数执行
	}

	// 查询指定驾校ID的驾校信息，并检查是否有错误或驾校是否存在
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(student.SchoolId))
	if err != nil || !ok {
		// 如果查询驾校信息时发生错误或驾校不存在，返回JSON格式的错误信息，错误码为201，消息为“查询驾校信息失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "查询驾校信息失败"})
		return // 结束函数执行
	}

	// 构建备案所需的数据，包含驾校的机构代码和学员的机构代码
	data := map[string]interface{}{
		"inscode": school.InstitutionCode,
		"stunum":  student.InstitutionCode,
	}

	// 通过GetSignURL函数获取备案请求的URL，并检查是否有错误
	if url, err = GetSignURL("transfer", data, reqType, school.Province, school.City); err != nil {
		// 如果获取URL时发生错误，返回JSON格式的错误信息，错误码为201，消息为具体的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return // 结束函数执行
	}

	// 声明一个ApiLog对象用于记录API请求日志
	var api_log models.ApiLog

	// 将data数据转换为JSON字符串，并赋值给api_log的Param字段
	params, _ := json.Marshal(data)
	api_log.Url = url
	api_log.Param = string(params)
	api_log.Method = "POST"
	api_log.Time = time.Now()

	// 发送API请求，并检查是否有错误
	if retMap, err = APIReq(url, data, "POST"); err != nil {
		// 将API请求的返回结果转换为JSON字符串，并赋值给api_log的Result字段
		result, _ := json.Marshal(retMap)
		api_log.Result = string(result)
		api_log.Add() // 将API请求日志添加到数据库
		// 如果发送API请求时发生错误，返回JSON格式的错误信息，错误码为201，消息为具体的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return // 结束函数执行
	}

	// 将API请求的返回结果转换为JSON字符串，并赋值给api_log的Result字段
	result, _ := json.Marshal(retMap)
	api_log.Result = string(result)
	api_log.Add() // 将API请求日志添加到数据库

	// 如果API请求成功，返回JSON格式的成功信息，错误码为201，消息为“成功”，包含返回的数据
	c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "成功", "data": retMap})
	return // 结束函数执行

}

func BindingCoach(c *gin.Context) {
	// 声明两个变量：student用于存储学员信息，studentId用于存储从请求中获取的学员ID字符串
	var (
		student   models.Student
		studentId string
	)

	// 从POST请求表单中获取"id"参数，并检查其是否为空
	if studentId = c.PostForm("id"); studentId == "" {
		// 如果"id"参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 将获取到的学员ID字符串转换为int64类型，并赋值给student的Id字段
	// 这里使用了strconv.ParseInt进行转换，并忽略了错误处理（用_接收错误）
	student.Id, _ = strconv.ParseInt(studentId, 10, 64)

	// 将学员的教练ID设置为0，表示解除与当前教练的绑定关系
	student.CoachId = 0

	// 调用student的Edit方法，尝试更新coach_id字段
	// 如果Edit方法返回false，表示解绑教练操作失败
	if !student.Edit("coach_id") {
		// 如果解绑教练操作失败，返回JSON格式的错误信息，错误码为201，消息为“学员解绑教练失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员解绑教练失败"})
		return // 结束函数执行
	}

	// 如果解绑教练操作成功，返回JSON格式的成功信息，错误码为200，消息为“学员解绑教练成功”
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "学员解绑教练成功"})
	return // 结束函数执行

}

func UnBindingCoach(c *gin.Context) {
	// 声明两个变量：student用于存储学员信息，studentId用于存储从请求中获取的学员ID字符串
	var (
		student   models.Student
		studentId string
	)

	// 从POST请求表单中获取"id"参数，并检查其是否为空
	if studentId = c.PostForm("id"); studentId == "" {
		// 如果"id"参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 将获取到的学员ID字符串转换为int64类型，并赋值给student的Id字段
	// 这里使用了strconv.ParseInt进行转换，并忽略了错误处理（用_接收错误）
	student.Id, _ = strconv.ParseInt(studentId, 10, 64)

	// 将学员的教练ID设置为0，表示解除与当前教练的绑定关系
	student.CoachId = 0

	// 调用student的Edit方法，尝试更新coach_id字段
	// 如果Edit方法返回false，表示解绑教练操作失败
	if !student.Edit("coach_id") {
		// 如果解绑教练操作失败，返回JSON格式的错误信息，错误码为201，消息为“学员解绑教练失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员解绑教练失败"})
		return // 结束函数执行
	}

	// 如果解绑教练操作成功，返回JSON格式的成功信息，错误码为200，消息为“学员解绑教练成功”
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "学员解绑教练成功"})
	return // 结束函数执行

}

func GetStudentPact(c *gin.Context) {
	// 声明两个变量，分别用于存储学校ID和汽车类型
	var (
		schoolId string
		carType  string
	)

	// 从POST请求表单中获取school_id参数，并检查其是否为空
	if schoolId = c.PostForm("school_id"); schoolId == "" {
		// 如果school_id参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 从POST请求表单中获取car_type参数，并检查其是否为空
	if carType = c.PostForm("car_type"); carType == "" {
		// 如果car_type参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 调用StudentPact模型的GetPact方法，根据schoolId和carType获取学员合同列表，并检查是否有错误发生
	list, err := new(models.StudentPact).GetPact(schoolId, carType)
	if err != nil {
		// 如果获取学员合同时发生错误，返回JSON格式的错误信息，错误码为201，消息为“获取学员合同失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "获取学员合同失败"})
		return // 结束函数执行
	}

	// 如果成功获取学员合同列表，返回JSON格式的成功信息，包含合同数据
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "学员合同获取成功", "data": list})
	return // 结束函数执行

}

func AddDStudentPact(c *gin.Context) {
	// 声明多个变量：schoolId用于存储学校ID，carType用于存储汽车类型，content用于存储合同内容，studentPact用于存储学员合同信息
	var (
		schoolId    string
		carType     string
		content     string
		studentPact models.StudentPact
	)

	// 从POST请求表单中获取"school_id"参数，并检查其是否为空
	if schoolId = c.PostForm("school_id"); schoolId == "" {
		// 如果"school_id"参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 从POST请求表单中获取"car_type"参数，并检查其是否为空
	if carType = c.PostForm("car_type"); carType == "" {
		// 如果"car_type"参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 从POST请求表单中获取"content"参数，并检查其是否为空
	if content = c.PostForm("content"); content == "" {
		// 如果"content"参数为空，返回JSON格式的错误信息，错误码为201，消息为“参数错误”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return // 结束函数执行
	}

	// 根据schoolId和carType获取学员合同列表，并忽略错误
	list, _ := new(models.StudentPact).GetPact(schoolId, carType)

	// 将获取到的schoolId字符串转换为int类型，并赋值给studentPact的SchoolId字段
	studentPact.SchoolId, _ = strconv.Atoi(schoolId)

	// 将carType赋值给studentPact的CarType字段
	studentPact.CarType = carType

	// 将content赋值给studentPact的Content字段
	studentPact.Content = content

	// 设置studentPact的Addtime字段为当前时间
	studentPact.Addtime = time.Now()

	// 检查获取到的学员合同列表是否为空
	if len(list) > 0 {
		// 如果列表不为空，将第一个合同的ID赋值给studentPact的Id字段
		studentPact.Id = list[0].Id
		// 更新合同内容和添加时间
		studentPact.Edit("content,addtime")
		// 返回JSON格式的成功信息，错误码为200，消息为“学员合同保存成功”
		c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "学员合同保存成功"})
		return // 结束函数执行
	} else {
		// 如果列表为空，尝试添加新的学员合同
		if !studentPact.Add() {
			// 如果添加新的学员合同时失败，返回JSON格式的错误信息，错误码为201，消息为“学员合同保存失败”
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员合同保存失败"})
			return // 结束函数执行
		}
		// 如果添加新的学员合同成功，返回JSON格式的成功信息，错误码为200，消息为“学员合同保存成功”
		c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "学员合同保存成功"})
		return // 结束函数执行
	}

}

func GetPactContent(c *gin.Context) {
	var (
		student        *models.Student
		user           *models.User
		pactResponse   response.PactResponse
		carType        string
		charstandardId string
		has            bool
		pact           models.HebeiPact
		sign           models.Studentsign
	)
	if c.PostForm("school_id") == "" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return
	}
	if c.PostForm("student_id") == "" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return
	}

	// 根据获取到的studentId查询学员信息，并检查是否有错误或学员是否存在
	ok, student, err := new(models.Student).GetStudentById(c.PostForm("student_id"))
	if err != nil || !ok {
		// 如果查询学员信息时发生错误或学员不存在，返回JSON格式的错误信息，错误码为201，消息为“学员不存在”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员不存在"})
		return // 结束函数执行
	}

	// 根据学员的UserId查询用户信息，并检查是否有错误
	user, err = new(models.User).GetUserById(student.UserId)
	if err != nil {
		// 如果查询用户信息时发生错误，返回JSON格式的错误信息，错误码为201，消息为“查询学员信息失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "查询学员信息失败"})
		return // 结束函数执行
	}

	// 查询指定驾校ID的驾校信息，并检查是否有错误或驾校是否存在
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(student.SchoolId))
	if err != nil || !ok {
		// 如果查询驾校信息时发生错误或驾校不存在，返回JSON格式的错误信息，错误码为201，消息为“查询驾校信息失败”
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "查询驾校信息失败"})
		return // 结束函数执行
	}
	filter1 := builder.NewCond()
	filter1 = filter1.And(builder.Eq{"id_number": user.IdNumber}).And(builder.Eq{"phone": user.Phone})
	sign, _ = new(models.Studentsign).GetOneStudentsignById(filter1)
	if school.District == "370982" {
		if sign.Id <= 0 {
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "学员还没有签名，请先完成签名！"})
			return
		}
	}
	carType = c.PostForm("car_type")
	charstandardId = c.PostForm("charstandard_id")
	if has, pact, _ = new(models.HebeiPact).GetByCond(c.PostForm("school_id"), carType, charstandardId); !has {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "未找到该合同模板"})
		return
	}
	pactResponse.PactNumber = strings.Replace(user.IdNumber, "t", "", -1)
	pactResponse.Legal = school.Legal
	pactResponse.LicenceNumber = school.LicenceNumber
	pactResponse.StudentAddress = user.Address
	pactResponse.SchoolAddress = school.Address
	pactResponse.SchoolName = school.Name
	pactResponse.Content = pact.Content
	pactResponse.SignUrl = sign.Imgurl
	pactResponse.Contract = sign.Contract
	pactResponse.CreditCode = school.CreditCode
	pactResponse.Phone = school.Phone
	pactResponse.SchoolUrl = school.Zhangurl
	c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "获取成功", "data": pactResponse})
	return
}

//func GetStudentRecord(c *gin.Context) {
//	var (
//		recordList []*response.RecordListResponse // 用于存储场地列表的响应
//		err        error
//	)
//	// 先查出学员所有的学时信息
//
//	recordList, err = new(models.LearnRecord).GetStudentRecordList(filter)
//
//	var subject1Records []*response.RecordListResponse
//	var subject2Records []*response.RecordListResponse
//	var subject3Records []*response.RecordListResponse
//	var subject4Records []*response.RecordListResponse
//
//	for _, v := range recordList {
//		switch v.Subject {
//		case "1":
//			subject1Records = append(subject1Records, v)
//		case "2":
//			subject2Records = append(subject2Records, v)
//		case "3":
//			subject3Records = append(subject3Records, v)
//		case "4":
//			subject4Records = append(subject4Records, v)
//		default:
//			// 处理未知科目
//			fmt.Println("未知科目:", v.Subject)
//		}
//	}
//	if err != nil {
//		return
//	}
//	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "获取成功", "data": gin.H{"subject1Records": subject1Records, "subject2Records": subject2Records, "subject3Records": subject3Records, "subject4Records": subject4Records}})
//	return
//}
